package com.leo.mybatis;

import com.leo.mybatis.mapper.IUserMapper;
import com.leo.mybatis.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class CacheTest {

    private IUserMapper userMapper;
    private SqlSession sqlSession;
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void before() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
         sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        sqlSession = sqlSessionFactory.openSession();
        userMapper = sqlSession.getMapper(IUserMapper.class);

    }

    /**
     * 一级缓存是SqlSession，默认开启，数据结构为HashMap，所以两次查询的对象是一样的
     * 但是一旦又新增，修改，删除操作，且提交了事务，则会清空一级缓存
     */
    @Test
    public void firstLevelCache(){
        // 第一次查询id为1的用户
        User user1 = userMapper.findUserById(1);

        // 第二次查询id为1的用户
        User user2 = userMapper.findUserById(1);

        // 两次查询的对象一样
        System.out.println(user1==user2);
    }



    @Test
    public void firstLevelCache2(){
        // 第一次查询id为1的用户
        User user1 = userMapper.findUserById(1);

        //更新用户
        User user = new User();
        user.setId(1);
        user.setUsername("tom");
        userMapper.updateUser(user);
        sqlSession.commit();
        sqlSession.clearCache();

        // 第二次查询id为1的用户
        User user2 = userMapper.findUserById(1);

        // 由于有更新操作且提交事务，所以一级缓存被清空，所以两次查询的对象不一样
        System.out.println(user1==user2);
    }


    /**
     * 二级缓存默认不开启，需要手动指定，在sqlMapConfig.xml和mapper.xml中都要设置
     * 如果是注解开发，则需要在DAO接口添加 @CacheNamespace，可以指定缓存的实现(LOCAL/REDIS... 一共12种缓存实现)
     */
    @Test
    public void SecondLevelCache(){
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();

        IUserMapper mapper1 = sqlSession1.getMapper(IUserMapper.class);
        IUserMapper mapper2 = sqlSession2.getMapper(IUserMapper.class);
        IUserMapper mapper3 = sqlSession3.getMapper(IUserMapper.class);

        User user1 = mapper1.findUserById(1);
        sqlSession1.close(); //清空一级缓存

        User user2 = mapper2.findUserById(1);

        // 不管有没有增删改操作并提交事务，对象都不同，因为二级缓存存的是序列化的数据，而非缓存对象
        // 所以entity对象需要实现Serializable接口
        System.out.println(user1==user2);
    }




    @Test
    public void SecondLevelCache2(){
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();

        IUserMapper mapper1 = sqlSession1.getMapper(IUserMapper.class);
        IUserMapper mapper2 = sqlSession2.getMapper(IUserMapper.class);
        IUserMapper mapper3 = sqlSession3.getMapper(IUserMapper.class);

        User user1 = mapper1.findUserById(1);
        sqlSession1.close(); //清空一级缓存


        User user = new User();
        user.setId(1);
        user.setUsername("lisi");
        mapper3.updateUser(user);
        sqlSession3.commit();

        User user2 = mapper2.findUserById(1);

        // 不管有没有增删改操作并提交事务，对象都不同，因为二级缓存存的是序列化的数据，而非缓存对象
        // 所以entity对象需要实现Serializable接口

        // 第二次查询还是发送了sql数据库查询，因为默认增删改并提交事务后会清空二级缓存
        System.out.println(user1==user2);
    }


}
